import * as fs from 'fs/promises';
import { LogLevel, LogEntry, LogConfig, LogBufferItem, LogMetrics } from '../types';
import { LogFormatter } from '../utils/logFormatter';
import { LogRotationService } from './logRotationService';
import { LogCleanupService } from './logCleanupService';
import { ConsoleRedirect } from '../utils/consoleRedirect';

export class LogManager {
  private static instance: LogManager | null = null;
  
  private config: LogConfig;
  private rotationService: LogRotationService;
  private cleanupService: LogCleanupService;
  private consoleRedirect: ConsoleRedirect;
  
  private isInitialized = false;
  private isShuttingDown = false;
  private writeBuffer: LogBufferItem[] = [];
  private writeTimer: NodeJS.Timeout | null = null;
  private isWriting = false;
  
  private metrics: LogMetrics = {
    totalEntries: 0,
    errorCount: 0,
    warnCount: 0,
    rotationCount: 0
  };

  private constructor(config: LogConfig) {
    this.config = config;
    this.rotationService = new LogRotationService(config);
    this.cleanupService = new LogCleanupService(config);
    this.consoleRedirect = new ConsoleRedirect({
      preserveConsole: process.env.NODE_ENV === 'development'
    });
  }

  /**
   * 获取LogManager单例实例
   */
  static getInstance(config?: LogConfig): LogManager {
    if (!LogManager.instance) {
      if (!config) {
        throw new Error('首次获取LogManager实例时必须提供配置');
      }
      LogManager.instance = new LogManager(config);
    }
    return LogManager.instance;
  }

  /**
   * 重置单例实例（主要用于测试）
   */
  static resetInstance(): void {
    LogManager.instance = null;
  }

  /**
   * 初始化日志系统
   */
  async initialize(): Promise<void> {
    if (this.isInitialized) {
      console.warn('日志系统已经初始化');
      return;
    }

    try {
      console.log('正在初始化日志系统...');

      // 检查配置有效性
      this.validateConfig();

      // 初始化轮转服务
      await this.rotationService.initialize();

      // 启动清理服务
      this.cleanupService.start();

      // 启动控制台重定向
      this.consoleRedirect.startRedirection(this.handleLogEntry.bind(this));

      // 启动缓冲写入定时器
      this.startWriteTimer();

      // 设置进程退出处理
      this.setupProcessHandlers();

      this.isInitialized = true;
      
      // 记录初始化完成日志
      this.log('INFO', 'LogManager', '日志系统初始化完成', {
        config: {
          directory: this.config.directory,
          rotation: this.config.rotation,
          level: this.config.level,
          maxFiles: this.config.maxFiles
        }
      });

      console.log('日志系统初始化完成');
    } catch (error) {
      console.error('日志系统初始化失败:', error);
      throw error;
    }
  }

  /**
   * 关闭日志系统
   */
  async shutdown(): Promise<void> {
    if (this.isShuttingDown) {
      return;
    }

    this.isShuttingDown = true;

    try {
      console.log('正在关闭日志系统...');

      // 停止写入定时器
      if (this.writeTimer) {
        clearInterval(this.writeTimer);
        this.writeTimer = null;
      }

      // 刷新剩余的缓冲区
      await this.flushBuffer();

      // 停止控制台重定向
      this.consoleRedirect.stopRedirection();

      // 停止清理服务
      this.cleanupService.stop();

      // 停止轮转服务
      await this.rotationService.stop();

      this.isInitialized = false;
      
      console.log('日志系统已关闭');
    } catch (error) {
      console.error('日志系统关闭失败:', error);
    }
  }

  /**
   * 记录日志
   */
  log(level: LogLevel, source: string, message: string, data?: any): void {
    if (!this.config.enabled || this.isShuttingDown) {
      return;
    }

    // 检查日志级别
    if (!LogFormatter.shouldLog(level, this.config.level)) {
      return;
    }

    const entry: LogEntry = {
      timestamp: new Date(),
      level,
      source,
      message: LogFormatter.sanitizeMessage(message),
      data
    };

    this.handleLogEntry(entry);
  }

  /**
   * 错误日志的便捷方法
   */
  error(source: string, message: string, error?: Error): void {
    const errorData = error ? {
      name: error.name,
      message: error.message,
      stack: error.stack
    } : undefined;

    this.log('ERROR', source, message, errorData);
  }

  /**
   * 警告日志的便捷方法
   */
  warn(source: string, message: string, data?: any): void {
    this.log('WARN', source, message, data);
  }

  /**
   * 信息日志的便捷方法
   */
  info(source: string, message: string, data?: any): void {
    this.log('INFO', source, message, data);
  }

  /**
   * 调试日志的便捷方法
   */
  debug(source: string, message: string, data?: any): void {
    if (this.config.enableDebugLog) {
      this.log('DEBUG', source, message, data);
    }
  }

  /**
   * 获取特定来源的日志记录器
   */
  getLogger(source: string) {
    return {
      error: (message: string, error?: Error) => this.error(source, message, error),
      warn: (message: string, data?: any) => this.warn(source, message, data),
      info: (message: string, data?: any) => this.info(source, message, data),
      debug: (message: string, data?: any) => this.debug(source, message, data),
      log: (message: string, data?: any) => this.info(source, message, data)
    };
  }

  /**
   * 立即刷新缓冲区
   */
  async flush(): Promise<void> {
    await this.flushBuffer();
  }

  /**
   * 手动触发日志轮转
   */
  async forceRotation(): Promise<void> {
    if (!this.isInitialized) {
      throw new Error('日志系统未初始化');
    }

    await this.flushBuffer();
    await this.rotationService.forceRotation();
    this.metrics.rotationCount++;
  }

  /**
   * 获取日志系统状态
   */
  getStatus(): {
    initialized: boolean;
    shuttingDown: boolean;
    bufferSize: number;
    metrics: LogMetrics;
    currentLogFile: string | null;
    rotationStats: any;
    cleanupStatus: any;
    redirectStats: any;
  } {
    return {
      initialized: this.isInitialized,
      shuttingDown: this.isShuttingDown,
      bufferSize: this.writeBuffer.length,
      metrics: { ...this.metrics },
      currentLogFile: this.rotationService.getCurrentLogFile(),
      rotationStats: this.rotationService.getRotationStats(),
      cleanupStatus: this.cleanupService.getStatus(),
      redirectStats: this.consoleRedirect.getStats()
    };
  }

  /**
   * 获取日志配置
   */
  getConfig(): LogConfig {
    return { ...this.config };
  }

  /**
   * 更新日志配置
   */
  updateConfig(newConfig: Partial<LogConfig>): void {
    const oldConfig = { ...this.config };
    this.config = { ...this.config, ...newConfig };

    // 如果级别改变了，记录配置更新
    if (oldConfig.level !== this.config.level) {
      this.info('LogManager', `日志级别已更新: ${oldConfig.level} -> ${this.config.level}`);
    }

    // 验证新配置
    this.validateConfig();
  }

  /**
   * 处理日志条目
   */
  private handleLogEntry(entry: LogEntry): void {
    try {
      // 更新统计信息
      this.updateMetrics(entry);

      // 格式化日志条目
      const formatted = LogFormatter.formatLogEntry(entry);

      // 添加到缓冲区
      this.writeBuffer.push({
        entry,
        formatted
      });

      // 如果缓冲区达到大小限制，立即刷新
      if (this.writeBuffer.length >= this.config.bufferSize) {
        setImmediate(() => this.flushBuffer());
      }
    } catch (error) {
      console.error('处理日志条目失败:', error);
    }
  }

  /**
   * 更新统计信息
   */
  private updateMetrics(entry: LogEntry): void {
    this.metrics.totalEntries++;
    
    switch (entry.level) {
      case 'ERROR':
        this.metrics.errorCount++;
        break;
      case 'WARN':
        this.metrics.warnCount++;
        break;
    }
  }

  /**
   * 刷新写入缓冲区
   */
  private async flushBuffer(): Promise<void> {
    if (this.isWriting || this.writeBuffer.length === 0) {
      return;
    }

    this.isWriting = true;

    try {
      const buffer = [...this.writeBuffer];
      this.writeBuffer = [];

      // 检查是否需要轮转
      if (this.rotationService.needsRotation()) {
        await this.rotationService.forceRotation();
        this.metrics.rotationCount++;
      }

      // 获取当前文件句柄
      const fileHandle = this.rotationService.getCurrentFileHandle();
      if (!fileHandle) {
        throw new Error('无有效的日志文件句柄');
      }

      // 批量写入
      const content = buffer.map(item => item.formatted).join('\\n') + '\\n';
      await fileHandle.write(content);

      // 强制刷新到磁盘
      await fileHandle.sync();
    } catch (error) {
      console.error('刷新日志缓冲区失败:', error);
      
      // 发生错误时，将缓冲区内容重新加入队列
      if (this.writeBuffer.length === 0) {
        // 如果缓冲区为空，说明这些条目丢失了，尝试降级处理
        console.error('日志写入失败，部分日志可能丢失');
      }
    } finally {
      this.isWriting = false;
    }
  }

  /**
   * 启动写入定时器
   */
  private startWriteTimer(): void {
    // 每秒检查一次是否需要刷新缓冲区
    this.writeTimer = setInterval(() => {
      if (this.writeBuffer.length > 0) {
        this.flushBuffer().catch(error => {
          console.error('定时刷新缓冲区失败:', error);
        });
      }
    }, 1000);
  }

  /**
   * 设置进程处理器
   */
  private setupProcessHandlers(): void {
    // 优雅退出处理
    const gracefulShutdown = async (signal: string) => {
      console.log(`收到 ${signal} 信号，正在关闭日志系统...`);
      await this.shutdown();
      process.exit(0);
    };

    process.on('SIGINT', () => gracefulShutdown('SIGINT'));
    process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));

    // 在进程退出前确保刷新缓冲区
    process.on('beforeExit', async () => {
      await this.shutdown();
    });
  }

  /**
   * 验证配置
   */
  private validateConfig(): void {
    if (!this.config.directory) {
      throw new Error('日志目录不能为空');
    }

    if (this.config.maxFiles <= 0) {
      throw new Error('最大文件数量必须大于0');
    }

    if (this.config.bufferSize <= 0) {
      throw new Error('缓冲区大小必须大于0');
    }

    if (this.config.maxFileSize <= 0) {
      throw new Error('最大文件大小必须大于0');
    }

    if (!LogFormatter.isValidLogLevel(this.config.level)) {
      throw new Error(`无效的日志级别: ${this.config.level}`);
    }
  }
}